#include "utils.h"
#include <iomanip>
#include <fstream>
#include <algorithm>
#include <unistd.h>
#include <sys/resource.h>

// Timer类实现
Timer::Timer(const std::string& name) : running(false), name(name) {}

void Timer::start() {
    start_time = std::chrono::high_resolution_clock::now();
    running = true;
}

void Timer::stop() {
    if (running) {
        end_time = std::chrono::high_resolution_clock::now();
        running = false;
    }
}

void Timer::reset() {
    running = false;
}

double Timer::elapsedMilliseconds() const {
    if (running) {
        auto now = std::chrono::high_resolution_clock::now();
        return std::chrono::duration<double, std::milli>(now - start_time).count();
    } else {
        return std::chrono::duration<double, std::milli>(end_time - start_time).count();
    }
}

double Timer::elapsedSeconds() const {
    return elapsedMilliseconds() / 1000.0;
}

void Timer::printElapsed(std::ostream& os) const {
    if (!name.empty()) {
        os << name << ": ";
    }
    
    double ms = elapsedMilliseconds();
    if (ms < 1000) {
        os << std::fixed << std::setprecision(3) << ms << " ms" << std::endl;
    } else {
        os << std::fixed << std::setprecision(3) << (ms / 1000.0) << " s" << std::endl;
    }
}

const std::string& Timer::getName() const {
    return name;
}

// ArgParser类实现
ArgParser::ArgParser(int argc, char** argv) : argc(argc), argv(argv) {}

int ArgParser::getInt(const std::string& option, int defaultValue) const {
    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];
        if (arg == option && i + 1 < argc) {
            try {
                return std::stoi(argv[i + 1]);
            } catch (const std::exception&) {
                return defaultValue;
            }
        }
    }
    return defaultValue;
}

float ArgParser::getFloat(const std::string& option, float defaultValue) const {
    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];
        if (arg == option && i + 1 < argc) {
            try {
                return std::stof(argv[i + 1]);
            } catch (const std::exception&) {
                return defaultValue;
            }
        }
    }
    return defaultValue;
}

std::string ArgParser::getString(const std::string& option, const std::string& defaultValue) const {
    for (int i = 1; i < argc; ++i) {
        std::string arg = argv[i];
        if (arg == option && i + 1 < argc) {
            return argv[i + 1];
        }
    }
    return defaultValue;
}

bool ArgParser::hasOption(const std::string& option) const {
    for (int i = 1; i < argc; ++i) {
        if (std::string(argv[i]) == option) {
            return true;
        }
    }
    return false;
}

void ArgParser::printHelp(std::ostream& os) const {
    os << "Usage: " << (argc > 0 ? argv[0] : "program") << " [options]" << std::endl;
    os << "Options:" << std::endl;
    os << "  -t, --threads <num>        Number of CPU threads to use" << std::endl;
    os << "  -T, --test-cases <num>     Number of test cases" << std::endl;
    os << "  -c, --cpu-only             Use CPU implementation only" << std::endl;
    os << "  -d, --dcu-only             Use DCU implementation only" << std::endl;
    os << "  -h, --hybrid               Use hybrid CPU+DCU implementation" << std::endl;
    os << "  -v, --validate             Validate results" << std::endl;
    os << "  --help                     Show this help message" << std::endl;
}

// MemoryUtils命名空间实现
namespace MemoryUtils {
    void printMemoryUsage(std::ostream& os) {
        struct rusage usage;
        if (getrusage(RUSAGE_SELF, &usage) == 0) {
            os << "Memory usage: " << (usage.ru_maxrss / 1024.0) << " MB" << std::endl;
        } else {
            os << "Failed to get memory usage" << std::endl;
        }
    }

    size_t getAvailableMemory() {
        size_t availableMem = 0;
        std::ifstream meminfo("/proc/meminfo");
        std::string line;
        
        if (meminfo.is_open()) {
            while (std::getline(meminfo, line)) {
                if (line.find("MemAvailable") != std::string::npos) {
                    std::istringstream iss(line);
                    std::string name;
                    size_t kb;
                    iss >> name >> kb;
                    availableMem = kb * 1024; // 转换为字节
                    break;
                }
            }
            meminfo.close();
        }
        
        return availableMem;
    }

    size_t getCurrentMemoryUsage() {
        struct rusage usage;
        if (getrusage(RUSAGE_SELF, &usage) == 0) {
            return usage.ru_maxrss * 1024; // 转换为字节
        }
        return 0;
    }
}

// ReportUtils命名空间实现
namespace ReportUtils {
    void printReportHeader(std::ostream& os) {
        os << std::left << std::setw(15) << "Implementation"
           << std::right << std::setw(6) << "M"
           << std::right << std::setw(6) << "N"
           << std::right << std::setw(6) << "K"
           << std::right << std::setw(15) << "Time (ms)"
           << std::right << std::setw(15) << "GFLOPS"
           << std::endl;
        
        os << std::string(60, '-') << std::endl;
    }

    void printReportLine(const std::string& implementation, int M, int N, int K, 
                         double timeMs, double gflops, std::ostream& os) {
        os << std::left << std::setw(15) << implementation
           << std::right << std::setw(6) << M
           << std::right << std::setw(6) << N
           << std::right << std::setw(6) << K
           << std::right << std::setw(15) << std::fixed << std::setprecision(3) << timeMs
           << std::right << std::setw(15) << std::fixed << std::setprecision(3) << gflops
           << std::endl;
    }

    double calculateGflops(int M, int N, int K, double timeSeconds) {
        // 矩阵乘法的浮点操作数：2*M*N*K (M*N*K次乘法和M*N*K次加法)
        double ops = 2.0 * M * N * K;
        return (ops / timeSeconds) / 1e9; // 转换为GFLOPS
    }
} 